package io.gitee.zhangbinhub.admin.common

import io.gitee.zhangbinhub.admin.common.conf.ZkClientConfiguration
import io.gitee.zhangbinhub.admin.common.serialnumber.GenerateSerialNumber
import io.gitee.zhangbinhub.admin.common.serialnumber.RedisGenerateSerialNumber
import org.apache.curator.framework.CuratorFramework
import org.apache.curator.framework.CuratorFrameworkFactory
import org.apache.curator.retry.RetryForever
import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinAutoConfiguration
import org.springframework.boot.autoconfigure.AutoConfiguration
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
import org.springframework.boot.autoconfigure.kafka.KafkaProperties
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.cloud.bus.jackson.BusJacksonAutoConfiguration
import org.springframework.cloud.bus.jackson.RemoteApplicationEventScan
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Import
import org.springframework.data.redis.core.RedisOperations
import org.springframework.data.redis.core.StringRedisTemplate
import zipkin2.reporter.Sender
import zipkin2.reporter.kafka.KafkaSender

/**
 * @author zhang by 30/07/2019
 * @since JDK 11
 */
@AutoConfiguration(before = [BusJacksonAutoConfiguration::class, ZipkinAutoConfiguration::class])
@EnableConfigurationProperties(ZkClientConfiguration::class)
@RemoteApplicationEventScan(basePackageClasses = [AcpAdminComponentAutoConfiguration::class])
@Import(RedisAutoConfiguration::class)
class AcpAdminComponentAutoConfiguration {
    @Bean
    @ConditionalOnClass(RedisOperations::class)
    @ConditionalOnMissingBean(GenerateSerialNumber::class)
    fun redisGenerateSerialNumber(stringRedisTemplate: StringRedisTemplate): GenerateSerialNumber =
        RedisGenerateSerialNumber(stringRedisTemplate)

    @Bean
    @ConditionalOnClass(CuratorFramework::class)
    @ConditionalOnMissingBean(CuratorFramework::class)
    fun acpZkClient(zkClientConfiguration: ZkClientConfiguration): CuratorFramework =
        CuratorFrameworkFactory.builder().apply {
            this.connectString(zkClientConfiguration.connect).sessionTimeoutMs(zkClientConfiguration.sessionTimeOut)
                .connectionTimeoutMs(zkClientConfiguration.connectionTimeOut)
                .retryPolicy(RetryForever(zkClientConfiguration.retryIntervalMs))
            if (zkClientConfiguration.aclEnable) {
                this.authorization(
                    zkClientConfiguration.aclSchema,
                    "${zkClientConfiguration.aclUsername}:${zkClientConfiguration.aclPassword}".toByteArray()
                )
            }
        }.build().apply { this.start() }

    @Bean
    @ConditionalOnMissingBean(Sender::class)
    fun zipkinKafkaSender(kafkaProperties: KafkaProperties): KafkaSender =
        KafkaSender.newBuilder().overrides(kafkaProperties.buildProducerProperties()).build()
}